package com.jin.webvideo.service;

import com.jin.webvideo.entity.Cache;
import com.jin.webvideo.entity.VideoInfo;
import com.jin.webvideo.mapper.ShareRoomMapper;
import com.jin.webvideo.mapper.VideoMapper;
import com.jin.webvideo.util.consts.ConfigConst;
import com.jin.webvideo.util.sys.EncryptUtil;
import com.jin.webvideo.util.base.MapBuilder;
import com.jin.webvideo.util.sys.SqlUtil;
import com.jin.webvideo.websocket.shareroom.ShareRoom;
import com.jin.webvideo.websocket.shareroom.ShareRoomManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service
public class ShareRoomService {
    @Autowired
    private CacheService cacheService;
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ShareRoomManager manager;
    @Autowired
    private ConfigService configService;

    public boolean supportShareRoom(String docid, String tvid, String platform){
        VideoInfo info = videoMapper.findVideoInfoByVid(docid, tvid, platform);
        if (null == info){
            return false;
        }
        Cache cache = cacheService.findCacheByUrl(info.getUrl());
        if (null != cache && cache.getStatus().equals(Cache.STATUS_CANPLAY)){
            return true;
        }
        String support = configService.configByGroupIdAndAttrid(ConfigConst.SHAREROOM_CONFIG, ConfigConst.ATTR_CONFIG_SUPPORTPLATFORM);
        return SqlUtil.arrayContain(support, platform);
    }
    public String createToken(String account, String roomId){
        long timestamp = EncryptUtil.timestamp() + 10000 * 10000;
        byte random = (byte) EncryptUtil.random(0, 16);
        byte[] roomIdByte = roomId.getBytes(StandardCharsets.UTF_8);
        byte[] accountByte = account.getBytes(StandardCharsets.UTF_8);
        ByteBuffer byteBuffer = ByteBuffer.allocate(16 + roomIdByte.length + accountByte.length);
        byteBuffer.putLong(timestamp);
        byteBuffer.putShort((short) account.length());
        byteBuffer.put(accountByte);
        byteBuffer.putShort((short) roomId.length());
        byteBuffer.put(roomIdByte);
        byte[] bs = byteBuffer.array();
        byte[] md5 = EncryptUtil.md5(bs);
        byteBuffer = ByteBuffer.allocate(bs.length + 17);
        byteBuffer.put(random);
        byteBuffer.put(md5);
        byteBuffer.put(EncryptUtil.offset(bs, random));
        return EncryptUtil.toHex(EncryptUtil.base64Encrypt(byteBuffer.array()));
    }
    public Map<String, String> checkToken(String token){
        byte[] bs = EncryptUtil.toByte(token);
        bs = EncryptUtil.base64Decrypt(bs);
        int random = bs[0] & 0xff;
        byte[] md5 = Arrays.copyOfRange(bs, 1, 17);;
        bs = Arrays.copyOfRange(bs, 17, bs.length);
        bs = EncryptUtil.offset(bs, -random);
        if (!EncryptUtil.equals(md5, EncryptUtil.md5(bs))){
            return null;
        }
        ByteBuffer buffer = ByteBuffer.allocate(bs.length);
        buffer.put(bs);
        buffer.flip();
        long timestamp = buffer.getLong();
        if (timestamp < EncryptUtil.timestamp()){
            return null;
        }
        byte[] temp = new byte[buffer.getShort()];
        buffer.get(temp);
        String account = new String(temp, StandardCharsets.UTF_8);
        temp = new byte[buffer.getShort()];
        buffer.get(temp);
        String roomId = new String(temp, StandardCharsets.UTF_8);
        return new MapBuilder<String,String>().put("account", account).put("roomId", roomId).build();
    }

    public long createRoom(String account){
        return manager.createRoom(account);
    }
    public ShareRoom findByRoomId(long roomid){
        return manager.findByRoomId(roomid);
    }
    public List<ShareRoom> listRoomInfo(){
        return manager.listAll();
    }
    public void closeRoom(long roomId){
        ShareRoom room = manager.findByRoomId(roomId);
        if (room == null){
            return ;
        }
        manager.closeRoom(room);
    }
}
